// 火焰弹（直线）
// @author:wangff8@qq.com  @date:2024-10-31
library SimulateAttac3 initializer init requires SimulateAttack

    globals
        // 火焰弹等级(默认0)
        integer array ct_hydLevel
        // 火焰弹CD(默认4秒)
        real array ct_hydCD
        // 火焰弹伤害增幅(默认0%)
        real array ct_hydDmgZf
        // 火焰弹爆炸范围（200，火焰弹击中后默认是爆炸的，切火焰弹的伤害都是火焰伤害，也就是红色字体）
        real array ct_hydBoomRang
        // 火焰弹爆炸范围增幅（默认0%）
        real array ct_hydBoomRangZf
        // 火焰弹爆炸伤害增幅（默认0%，爆炸造成范围攻击力*1的伤害）
        real array ct_hydBoomDmgZf
        // 火焰弹连放次数(默认0)
        integer array ct_hydAttCount

    endglobals

    private function init takes nothing returns nothing
        local integer uid = 0
        loop
            exitwhen uid > PLAYER_NUMBER
            set ct_hydLevel[uid] = 0
            set ct_hydCD[uid] = 4.0
            set ct_hydDmgZf[uid] = 0.0
            set ct_hydBoomRang[uid] = 220.0
            set ct_hydBoomRangZf[uid] = 0.0
            set ct_hydBoomDmgZf[uid] = 0.0
            set ct_hydAttCount[uid] = 0
            set uid = uid + 1
        endloop
    endfunction

    // 火焰弹命中爆炸
    // 火焰弹中怪物后对100码范围造成攻击*1.0的伤害
    private function hydBoom takes integer uid, real x, real y returns nothing
        local group g = CreateGroup()
        local boolexpr filter
        local unit ydl_unit
        local unit u = udg_player_select_hero[uid]
        local effect ect
        local real shv = FF_GetAttack(u) * 1.0 * (ct_hydBoomDmgZf[uid] + 1.0)
        // 范围增幅
        local real zf = ct_hydBoomRangZf[uid] + 1.0

        // 特效 
        if tx_show_status[uid] == 1 then
            set ect = AddSpecialEffect("tx_fire_bz.mdx", x, y)
            call EXSetEffectSize(ect, 1.2 * zf)
            call DestroyEffect(ect)
        endif

        set filter = Condition(function heroSkillConditions)
        call GroupEnumUnitsInRange(g, x, y, ct_hydBoomRang[uid] * zf, filter)
        loop
            set ydl_unit = FirstOfGroup(g)
            exitwhen (ydl_unit == null)
            call GroupRemoveUnit(g, ydl_unit)
            call UnitDamageTarget( u, ydl_unit, shv, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS )
        endloop

        call DestroyBoolExpr(filter)
        call DestroyGroup(g)

        set ect = null
        set u = null
        set g = null
        set filter = null
        set ydl_unit = null
    endfunction

    // 攻击弹道 
    function timer_sfhyd takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer tid = GetHandleId(t)
        local integer uid = LoadInteger(gameht, tid, 1)
        // 单位
        local unit u = LoadUnitHandle(gameht, tid, 9)
        local unit bu = LoadUnitHandle(gameht, tid, 10)
        local effect ect = LoadEffectHandle(gameht, tid, 3)
        // 移动次数
        // 要移动的距离
        local real jl = LoadReal(gameht, tid, 4) + 35
        local real shv = LoadReal(gameht, tid, 8)
    
        local real x0 = GetUnitX(u)
        local real y0 = GetUnitY(u)
        local real order_x = GetUnitX(bu)
        local real order_y = GetUnitY(bu)
        local real jd = getAngleBetweenXY(x0, y0, order_x, order_y)
        // 计算出马甲创建的位置
        local real x = CosBJ(jd) * (jl) + LoadReal(gameht, tid, 6)
        local real y = SinBJ(jd) * (jl) + LoadReal(gameht, tid, 7)
        // 总距离
        // local real totalJl = LoadReal(gameht, tid, 12)
        local real totalJl = getDistance(x0, y0, order_x, order_y)
        local real height = LoadReal(gameht, tid, 2)

        // 刷新上一次移动的位置
        if order_x != 0.0 or order_y != 0.0 then
            call SaveReal(gameht, tid, 20, order_x)
            call SaveReal(gameht, tid, 21, order_y)
        endif

        if order_x == 0.0 and order_y == 0.0 then
            set order_x = LoadReal(gameht, tid, 20)
            set order_y = LoadReal(gameht, tid, 21)
            set jd = getAngleBetweenXY(x0, y0, order_x, order_y)
            // 计算出马甲创建的位置
            set x = CosBJ(jd) * (jl) + LoadReal(gameht, tid, 6)
            set y = SinBJ(jd) * (jl) + LoadReal(gameht, tid, 7)
            set totalJl = getDistance(x0, y0, order_x, order_y)
        endif


        // // 设置弹道转向
        // call EXEffectMatRotateZ(ect, jd)
        // 设置弹道位置
        call EXSetEffectXY( ect, x, y )
        call EXSetEffectZ( ect, getZByXY(x, y) + height )        
    
        // 退出计时
        call SaveReal(gameht, tid, 4, jl)
        if(jl >= totalJl) then
            // 造成伤害 法术伤害
            call UnitDamageTarget( u, bu, shv, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS )

            call hydBoom(uid, x, y)

            call DestroyEffect(ect)
            call FlushChildHashtable(gameht, tid)
            call PauseTimer(t)
            call DestroyTimer(t)
        endif
    
        set u = null
        set bu = null
        set t = null
        set ect = null
    endfunction

    // 释放火焰弹
    private function relHuoYD takes unit u, unit bu, string ddmdl, real shv, real height returns nothing
    
        local integer uid = GetPlayerId(GetOwningPlayer(u))
        local timer t
        local integer tid
        local effect ect
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real order_x = GetUnitX(bu)
        local real order_y = GetUnitY(bu)
        local real jd = getAngleBetweenXY(x, y, order_x, order_y)

        set ect = AddSpecialEffect(ddmdl, x, y)
        call EXSetEffectZ( ect, getZByXY(x, y) + height )
        call EXEffectMatRotateZ(ect, jd)

        set t = CreateTimer()
        set tid = GetHandleId(t)
        call SaveInteger(gameht, tid, 1, uid)
        call SaveReal(gameht, tid, 2, height)
        // call SaveReal(gameht, tid, 12, getDistance(x, y, order_x, order_y))
        call SaveEffectHandle(gameht, tid, 3, ect)
        call SaveReal(gameht, tid, 6, x)
        call SaveReal(gameht, tid, 7, y)
        call SaveReal(gameht, tid, 8, shv)
        call SaveUnitHandle(gameht, tid, 9, u)
        call SaveUnitHandle(gameht, tid, 10, bu)

        // 第一次的坐标，如果目标单位被打死了删除了，他的坐标会变为0，就使用这个
        // 每次移动位置刷新这个坐标，如果不是0就记录，等为0的时候就使用这个
        call SaveReal(gameht, tid, 20, order_x)
        call SaveReal(gameht, tid, 21, order_y)

        call TimerStart(t, 0.02, true, function timer_sfhyd)

        set u = null
        set bu = null
        set ddmdl = null
        set ect = null
        set t = null
    endfunction

    // 在释放一次
    function timer_releseHYD takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer tid = GetHandleId(t)
        local integer uid = LoadInteger(gameht, tid, 0)
        local unit u = LoadUnitHandle(gameht, tid, 1)
        local unit bu = getNearestUnit(uid)
        local string ddmdl = LoadStr(gameht, tid, 3)
        local real shv = LoadReal(gameht, tid, 4)
        local real height = LoadReal(gameht, tid, 5)
        local integer count = LoadInteger(gameht, tid, 6) + 1

        call SaveInteger(gameht, tid, 6, count)
        call relHuoYD(u, bu, ddmdl, shv, height)
        if count >= ct_hydAttCount[uid] then
            call FlushChildHashtable(gameht, tid)
            call DestroyTimer(t)
        endif

        set ddmdl = null
        set t = null
        set u = null
        set bu = null
    endfunction

    // 释放火焰弹
    function releseHYD takes integer uid returns nothing
        local unit u = udg_player_select_hero[uid]
        local unit bu = getNearestUnit(uid)
        local string ddmdl = "tsw_huoyd.mdx"
        local real shv = FF_GetAttack(u) * 1.2 * (1.0 + ct_hydDmgZf[uid])
        local real height = 80.0
        local timer t
        local integer tid
        
        call relHuoYD(u, bu, ddmdl, shv, height)

        if ct_hydAttCount[uid] > 0 then
            set t = CreateTimer()
            set tid = GetHandleId(t)

            call SaveInteger(gameht, tid, 0, uid)
            call SaveUnitHandle(gameht, tid, 1, u)
            call SaveStr(gameht, tid, 3, ddmdl)
            call SaveReal(gameht, tid, 4, shv)
            call SaveReal(gameht, tid, 5, height)

            call TimerStart(t, 0.5, true, function timer_releseHYD)
        endif

        set u = null
        set bu = null
        set ddmdl = null
        set t = null
    endfunction
    
endlibrary



